!! Copyright (C) 2009,2010,2011,2012  Marco Restelli
!!
!! This file is part of:
!!   FEMilaro -- Finite Element Method toolkit
!!
!! FEMilaro is free software; you can redistribute it and/or modify it
!! under the terms of the GNU General Public License as published by
!! the Free Software Foundation; either version 3 of the License, or
!! (at your option) any later version.
!!
!! FEMilaro is distributed in the hope that it will be useful, but
!! WITHOUT ANY WARRANTY; without even the implied warranty of
!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
!! General Public License for more details.
!!
!! You should have received a copy of the GNU General Public License
!! along with FEMilaro; If not, see <http://www.gnu.org/licenses/>.
!!
!! author: Marco Restelli                   <marco.restelli@gmail.com>

module mod_messages
!General comments: defines errors, warinings and infos. Use array of
! strings to separate messages into multiple lines.
!-----------------------------------------------------------------------

!-----------------------------------------------------------------------

 use mod_utils, only: &
   my_abort

!-----------------------------------------------------------------------
 
 implicit none

!-----------------------------------------------------------------------

! Module interface

 public :: &
   mod_messages_constructor, &
   mod_messages_destructor,  &
   mod_messages_initialized, &
   error,   &
   warning, &
   info

 private

!-----------------------------------------------------------------------

! Module types and parameters

 ! private members
 integer, parameter ::                &
   sterr = 0, &
   stout = 1

! Module variables

 ! public members
 logical ::               &
   mod_messages_initialized = .false.
 ! private members
 character(len=*), parameter :: &
   this_mod_name = 'mod_messages'

 interface error
   module procedure error, error_multiline
 end interface
 interface warning
   module procedure warning, warning_multiline
 end interface
 interface info
   module procedure info, info_multiline
 end interface

!-----------------------------------------------------------------------

contains

!-----------------------------------------------------------------------

 subroutine mod_messages_constructor()
  character(len=*), parameter :: &
    this_sub_name = 'constructor'

   !Consistency checks ---------------------------
   if(mod_messages_initialized.eqv..true.) then
     call warning(this_sub_name,this_mod_name, &
                  'Module already initialized')
   endif
   !----------------------------------------------

   mod_messages_initialized = .true.
 end subroutine mod_messages_constructor

!-----------------------------------------------------------------------
 
 subroutine mod_messages_destructor()
  character(len=*), parameter :: &
    this_sub_name = 'destructor'
   
   !Consistency checks ---------------------------
   if(mod_messages_initialized.eqv..false.) then
     call warning(this_sub_name,this_mod_name, &
                  'Module is not initialized')
   endif
   !----------------------------------------------
   
   mod_messages_initialized = .false.
 end subroutine mod_messages_destructor

!-----------------------------------------------------------------------
 
 subroutine error(caller,caller_mod,text)
  character(len=*), intent(in) :: &
    caller, caller_mod, text
 
  character(len=*), parameter :: &
    this_sub_name = 'error'

   write(sterr,'(/A,A,A,A,A/A,A/)') &
     'ERROR in "', caller, '", in module "', caller_mod, '"!', &
     '  ',trim(text)
   call my_abort()
 
 end subroutine error
 
!-----------------------------------------------------------------------
 
 subroutine error_multiline(caller,caller_mod,text)
  character(len=*), intent(in) :: &
    caller, caller_mod, text(:)
 
  character(len=*), parameter :: &
    this_sub_name = 'error'
  integer :: i
  character(len=100) :: snline
  character(len=12+100+8) :: out_format

   write(snline,*) size(text) 
   write(out_format,'(A,A,A)') &
     '(/A,A,A,A,A/',trim(adjustl(snline)),'(2x,A/))'
   write(sterr,trim(out_format)) &
     'ERROR in "', caller, '", in module "', caller_mod, '"!', &
     (trim(text(i)),i=1,size(text))
   call my_abort()
 
 end subroutine error_multiline

!-----------------------------------------------------------------------
 
 subroutine warning(caller,caller_mod,text)
  character(len=*), intent(in) :: &
    caller, caller_mod, text
 
  character(len=*), parameter :: &
    this_sub_name = 'warning'

   write(sterr,'(/A,A,A,A,A/A,A/)') &
     'WARNING in "', caller, '", in module "', caller_mod, '"!', &
     '  ',trim(text)
 
 end subroutine warning
 
!-----------------------------------------------------------------------
 
 subroutine warning_multiline(caller,caller_mod,text)
  character(len=*), intent(in) :: &
    caller, caller_mod, text(:)
 
  character(len=*), parameter :: &
    this_sub_name = 'error'
  integer :: i
  character(len=100) :: snline
  character(len=12+100+8) :: out_format

   write(snline,*) size(text) 
   write(out_format,'(A,A,A)') &
     '(/A,A,A,A,A/',trim(adjustl(snline)),'(2x,A/))'
   write(sterr,trim(out_format)) &
     'WARNING in "', caller, '", in module "', caller_mod, '"!', &
     (trim(text(i)),i=1,size(text))
 
 end subroutine warning_multiline

!-----------------------------------------------------------------------
 
 subroutine info(caller,caller_mod,text)
  character(len=*), intent(in) :: &
    caller, caller_mod, text
 
  character(len=*), parameter :: &
    this_sub_name = 'info'
 
   write(*,'(/A,A,A,A,A/A,A/)') &
     'INFO from "', caller, '", in module "', caller_mod, '":', &
     '  ',trim(text)
 
 end subroutine info
 
!-----------------------------------------------------------------------
 
 subroutine info_multiline(caller,caller_mod,text)
  character(len=*), intent(in) :: &
    caller, caller_mod, text(:)
 
  character(len=*), parameter :: &
    this_sub_name = 'error'
  integer :: i
  character(len=100) :: snline
  character(len=12+100+8) :: out_format

   write(snline,*) size(text) 
   write(out_format,'(A,A,A)') &
     '(/A,A,A,A,A/',trim(adjustl(snline)),'(2x,A/))'
   write(*,trim(out_format)) &
     'INFO from "', caller, '", in module "', caller_mod, '":', &
     (trim(text(i)),i=1,size(text))
 
 end subroutine info_multiline

!-----------------------------------------------------------------------

end module mod_messages

